package com.inspur.edp.udt.designtime.manager;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.spi.MetadataContentSerializer;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;

import com.inspur.edp.udt.designtime.api.exception.UdtModelErrorCodeEnum;
import com.inspur.edp.udt.designtime.api.exception.UdtModelException;
import com.inspur.edp.udt.designtime.manager.services.UpdateElementService;
import java.io.IOException;

import com.inspur.edp.udt.designtime.api.utils.Context;
import com.inspur.edp.udt.designtime.api.utils.UdtThreadLocal;

public class ContentSerializer implements MetadataContentSerializer {

	String serializeResult = "{\n" +
			"    \"Type\": \"SimpleDataType\",\n" +
			"    \"Content\": {}}";
	String simpleUdtType = "SimpleDataType";
	String complexUdtType = "ComplexDataType";
	String para_Type = "Type";
	String para_Content = "Content";

	@Override
	public JsonNode Serialize(IMetadataContent iMetadataContent) {
		Context context = new Context();
		context.setfull(false);
		UdtThreadLocal.set(context);
		ObjectMapper mapper = new ObjectMapper();
		try {
			JsonNode result = mapper.readTree(serializeResult);
			if (iMetadataContent.getClass().isAssignableFrom(SimpleDataTypeDef.class)) {
				String jsonResult = mapper.writeValueAsString((SimpleDataTypeDef) iMetadataContent);
				((ObjectNode) result).put(para_Type, simpleUdtType);
				JsonNode sUdtJson = mapper.readTree(jsonResult);
				((ObjectNode)result).set(this.para_Content, sUdtJson);
				UdtThreadLocal.unset();
				return result;
			} else if (iMetadataContent.getClass().isAssignableFrom(ComplexDataTypeDef.class)) {
				String jsonResult = mapper.writeValueAsString((ComplexDataTypeDef) iMetadataContent);
				((ObjectNode) result).put(para_Type, complexUdtType);
				JsonNode cUdtJson = mapper.readTree(jsonResult);
				((ObjectNode)result).set(this.para_Content, cUdtJson);
				UdtThreadLocal.unset();
				return result;
			} else {
				UdtThreadLocal.unset();
				throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_ENUM_NOTSUPPORT_0005, iMetadataContent.getClass().getTypeName());
			}
		} catch (IOException e) {
			UdtThreadLocal.unset();
			// 仅拦截具体的序列化异常, 可确定iMetadataContent是UDT类型.
			throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0005, e, "UnifiedDataTypeDef", ((UnifiedDataTypeDef) iMetadataContent).getName());
		}
	}

	@Override
	public IMetadataContent DeSerialize(JsonNode metaJsonNode) {
		ObjectMapper mapper = new ObjectMapper();
    UpdateElementService elementService= UpdateElementService.getInstance();
		JsonNode jsonNode = null;
		try {
			jsonNode = mapper.readTree(handleJsonString(metaJsonNode.toString()));
		} catch (IOException e) {
			throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0003, e);
 		}
		String componentType = jsonNode.get(para_Type).textValue();
		String dataType = handleJsonString(jsonNode.get(para_Content).toString());
		if (complexUdtType.equals(componentType)) {
			try {
			  ComplexDataTypeDef complexDataTypeDef=mapper.readValue(dataType,ComplexDataTypeDef.class);
			  complexDataTypeDef.updateColumnsInfo();
        elementService.handleComplexUdtChildAsso(complexDataTypeDef);
				return complexDataTypeDef;
			} catch (IOException e) {
				throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0001, e, "ComplexDataTypeDef");
			}
		}
		if (simpleUdtType.equals(componentType)) {
			try {
			  SimpleDataTypeDef simpleDataTypeDef=mapper.readValue(dataType, SimpleDataTypeDef.class);
			  simpleDataTypeDef.updateColumnsInfo();
			  elementService.handleSimpleUdtChildAsso(simpleDataTypeDef);

				return simpleDataTypeDef;
			} catch (IOException e) {
				throw UdtModelException.createException(UdtModelErrorCodeEnum.GSP_BEMODEL_JSON_0001, e, "SimpleDataTypeDef");
			}
		}
		return null;
	}

	private static String handleJsonString(String contentJson) {
		if (!contentJson.startsWith("\"")) {
			return contentJson;
		}
		contentJson = contentJson.replace("\\r\\n", "");
		contentJson = contentJson.replace("\\\"{", "{");
		contentJson = contentJson.replace("}\\\"", "}");
		while (contentJson.startsWith("\"")) {
			contentJson = contentJson.substring(1, contentJson.length() - 1);
		}

		contentJson = contentJson.replace("\\\"", "\"");
		contentJson = contentJson.replace("\\\\", "");
		return contentJson;
	}
}
